package configuration;

import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;

import mutationMethods.ExchangeMutator;
import mutationMethods.FlippingMutator;
import mutationMethods.Mutator;
import mutationMethods.RevertMutator;

import crossingMethods.DPCrossover;
import crossingMethods.Reproductor;
import crossingMethods.SPCrossover;
import crossingMethods.UPCrossover;

import objectiveFunctions.AdjustedFitnessFunction;
import objectiveFunctions.CollisionFitnessFunction;
import objectiveFunctions.CuadMedErrorFitnessFunction;
import objectiveFunctions.GeneticFitnessFunction;
import objectiveFunctions.NormalizedFitnessFunction;
import objectiveFunctions.StandarizedFitnessFunction;

import replacementMethods.BothParentsReplacement;
import replacementMethods.RandomReplacement;
import replacementMethods.Replacement;
import replacementMethods.WeakParentReplacement;
import selectionMethods.RankingSelector;
import selectionMethods.RankingSelectorRNA;
import selectionMethods.RouletteSelector;
import selectionMethods.Selector;
import selectionMethods.TournamentSelector;
import selectionMethods.TournamentSelectorRNA;
import stoppingCriteria.AmountOfGenerationsCriteria;
import stoppingCriteria.FitnessValueCriteria;
import stoppingCriteria.GeneticStoppingCriterion;
import stoppingCriteria.NumberCyclesCriteria;


public class ConfigGeneticNR {
   
    private static ConfigGeneticNR instance;

    private int age;
    private int populationSize;
    private double crossProbability;
    private double mutationProbability;
    private String chromosomeRepresentation;
    private String selectionStrategy;
    private String populationStrategy;
	private String replacementStrategy;
	private String reproductionStrategy;
	private String mutatorStrategy;
	private String geneticStoppingCriteria;
	private double lowerRange;
	private double topRange;
	private String geneticFitnessFunction;
	private double valueStopCriteria;
	private int chromosomeSize;
    private String validator;
    private int criteriaBestValue;
    private int geneSize;
    

    private ConfigGeneticNR() {
    	super();
    }

    private static void loadConfig(String configFile) throws IOException {
    	
        Properties property = new Properties();
        FileReader f = new FileReader(configFile);
        property.load(f);
        f.close();

        instance = new ConfigGeneticNR();
        //empiezo a buscar los parametros
        instance.populationSize = Integer.parseInt(property.getProperty("populationSize"));
        instance.mutationProbability=Double.parseDouble(property.getProperty("mutationProbability"));
        instance.crossProbability=Double.parseDouble(property.getProperty("crossProbability"));
        instance.chromosomeRepresentation=property.getProperty("chromosomeRepresentation");
        instance.selectionStrategy= property.getProperty("selectionStrategy");
        instance.populationStrategy=property.getProperty("populationStrategy");
        instance.reproductionStrategy=property.getProperty("reproductionStrategy");
        instance.replacementStrategy=property.getProperty("replacementStrategy");
        instance.mutatorStrategy=property.getProperty("mutatorStrategy");
        instance.geneticStoppingCriteria=property.getProperty("geneticStoppingCriteria");
        instance.valueStopCriteria=Double.valueOf(property.getProperty("valueStoppingCriteria"));
        instance.geneticFitnessFunction=property.getProperty("geneticFitnessFunction");
        instance.chromosomeSize=Integer.valueOf(property.getProperty("chromosomeSize"));
        instance.lowerRange=Double.valueOf(property.getProperty("geneLowerRange"));
        instance.topRange=Double.valueOf(property.getProperty("geneTopRange"));
        //este va a uno para esta solucion 
        instance.geneSize = 1;
        
    }

    public static ConfigGeneticNR getInstance(String configFile) throws IOException {
        if (instance == null) {
            loadConfig(configFile);
        }
        return instance;
    }
	public int getPopulationSize() {
		return this.populationSize;
	}

	
	
	public int getGeneSize() {
		return geneSize;
	}

	public void setGeneSize(int geneSize) {
		this.geneSize = geneSize;
	}

	public Selector getSelectionStrategy()
    {
    	Selector sel=null;
    	switch(this.selectionStrategy)
    	{
    	case "RouletteSelector":

    		sel = new RouletteSelector();
    		break;
    	case "TournamentSelector":
    		sel = new TournamentSelector();
    		break;
    	case "TournamentSelectorRNA":
    		sel = new TournamentSelectorRNA();
    		break;	
    	case "RankingSelector":
    		sel = new RankingSelector();
    		break;    				
    	case "RankingSelectorRNA":
    		sel = new RankingSelectorRNA();
    		break;    				

    	}
    
    	return sel;
    }

	public double getMutationProbability() {
		return this.mutationProbability;
	}

	public double getCrossProbability() {
		return this.crossProbability;
	}

	public String getChromosomeRepresentation() {
		// TODO Auto-generated method stub
		return this.chromosomeRepresentation;
	}

	public String getPopulationStrategy() {
		return this.populationStrategy;
	}

	public Replacement getReplacementStrategy() {

		Replacement replace = null;
		switch(this.replacementStrategy){
		
		case "BothParentsReplacement":
			replace = new BothParentsReplacement();
			break;
		case "RandomReplacement":
			replace = new RandomReplacement();
			break;
		case "WeakParentReplacement":
			replace=new WeakParentReplacement();
			break;
		}
			
		return replace;
	}

	public Reproductor getReproductionStrategy() {
			Reproductor rep=null;
			switch(this.reproductionStrategy)
			{
			case "SPCrossover":
				rep = new SPCrossover();
				return rep;
			case "DPCrossover":
				rep = new DPCrossover();
				return rep;
			case "UPCrossover":
				rep = new UPCrossover();
				return rep;
			
			}
			return rep;
	}

	public Mutator getMutatorStrategy() {
		
		Mutator mutator = null;
		//crear el mutador
		switch(this.mutatorStrategy)
		{
		case "FlippingMutator":
			mutator= new FlippingMutator();
			break;
		case "ExchangeMutator":
			mutator = new ExchangeMutator();
			break;
		case "RevertMutator":
			mutator = new RevertMutator();
			break;
	
		}
		return mutator;
	}
	

	/**
	 * 
	 * @return un objeto de tipo GeneticStoppingCriterion
	 * que se usa para iniciar el algoritmo Genetico 
	 */
	public GeneticStoppingCriterion getGeneticStoppingCriteria() {
		// TODO Auto-generated method stub
		GeneticStoppingCriterion stopCriteria = null;
		switch(this.geneticStoppingCriteria)
		{
		case "NumberCyclesCriteria": 
			stopCriteria=new NumberCyclesCriteria();
			break;
		case "AmountOfGenerationsCriteria":
			stopCriteria=new AmountOfGenerationsCriteria();
			break;
		case "FitnessValueCriteria":
			stopCriteria=new FitnessValueCriteria();
			break;
			
		}
		//seteo el valor de comparacion parametro para evaluar si el criterio se alcanzo
		stopCriteria.setValueStop(this.valueStopCriteria);
		return stopCriteria;
	}

	public double getValueStopCriteria() {
		return this.valueStopCriteria;
	}

	public GeneticFitnessFunction getGeneticFitnessFunction() {
		//la unica funcion que uso es esta, porque es un caso especifico
		GeneticFitnessFunction fitnessFunction=null;
		CollisionFitnessFunction  f = new CollisionFitnessFunction(this.criteriaBestValue);
		f.setTamanioTablero(this.chromosomeSize);
		fitnessFunction=f;
		return fitnessFunction;
	}
	
	public int getChromosomeSize() {
			
			return this.chromosomeSize;
		}

	public double getLowerRange() {
		return this.lowerRange;
	}

	public double getTopRange() {
		return this.topRange;
	}	
}//end class
